#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include "StdTcp.h"

struct TcpServer//用于保存服务器的套接字
{
    int sock;
};

TcpS *InitTcpServer(const char *ip, short int port)//初始化TCP服务器的函数
{
    TcpS *s = (TcpS *)malloc(sizeof(TcpS));
    if (s == NULL)
    {//检查内存分配是否成功。如果分配失败，打印错误信息并返回NULL。
        printf("InitTcpServer malloc error!\n");
        return NULL;
    }
    //通过malloc函数动态分配了一个TcpS结构体的内存，用于存储服务器的相关信息。
    s->sock = socket(AF_INET, SOCK_STREAM, 0);//使用socket函数创建一个TCP套接字。
    if (s->sock < 0)
    {
        perror("socket:");
        free(s);
        return NULL;
    }
//创建套接字：使用socket函数创建一个TCP套接字，并将返回的套接字文件描述符保存在s->sock变量中。
    int on = 1;//设置套接字选项
    if (setsockopt(s->sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0)//用于设置套接字选项的系统调用
    {//SO_REUSEADDR用于允许地址重用
        perror("setsockopt:");
        free(s);
        return NULL;
    }

    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);//将端口号转换为网络字节序
    addr.sin_addr.s_addr = inet_addr(ip);//将IP地址字符串转换为网络字节序的32位二进制IP地址

    if (bind(s->sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
    {//将套接字与指定的IP地址和端口号绑定在一起。
        perror("bind:");
        free(s);
        return NULL;
    }

    if (listen(s->sock, 10) != 0)//使用listen函数开始监听指定套接字上的新连接请求。
    {
        perror("listen:");
        free(s);
        return NULL;
    }
    return s;
}

int TcpServerAccept(TcpS *s)
{//用于接受客户端的连接请求并创建一个新的套接字来处理与客户端的通信。
    struct sockaddr_in addr;
    socklen_t len; //= sizeof(addr);
    int acceptSock = 0;

    if ((acceptSock = accept(s->sock, (struct sockaddr *)&addr, &len)) < 0)
    {
        perror("accept:");
        return -1;
    }
    return acceptSock;
}

void TcpServerSend(int ClientSock, void *ptr, size_t size)
{
    if (send(ClientSock, ptr, size, 0) < 0)
    {//用于在网络通信中发送数据的函数
        perror("send:");
    }
}

void TcpServerRecv(int ClientSock, void *ptr, size_t size)
{
    if (recv(ClientSock, ptr, size, 0) < 0)
    {//用于在网络通信中接收数据的函数
        perror("recv:");
    }
}

void ClearTcpServer(TcpS *s)
{
    close(s->sock);
    free(s);
}

struct TcpClient
{
    int sock;
};

TcpC *InitTcpClient(const char *serverIp, short int serverPort)
{
    TcpC *c = (TcpC *)malloc(sizeof(TcpC));
    if (c == NULL)
    {
        printf("InitTcpClient malloc error!\n");
        return NULL;
    }

    c->sock = socket(AF_INET, SOCK_STREAM, 0);
    if (c->sock < 0)
    {
        perror("socket:");
        free(c);
        return NULL;
    }
    struct sockaddr_in ServerAddr;
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(serverPort);
    ServerAddr.sin_addr.s_addr = inet_addr(serverIp);
    if (connect(c->sock, (struct sockaddr *)&ServerAddr, sizeof(ServerAddr)) != 0)
    {
        perror("connect:");
        free(c);
        return NULL;
    }
    return c;
}

void TcpClientSend(TcpC *c, void *ptr, size_t size)
{
    if (send(c->sock, ptr, size, 0) < 0)
    {
        perror("send:");
    }
}

void TcpClientRecv(TcpC *c, void *ptr, size_t size)
{
    if (recv(c->sock, ptr, size, 0) < 0)
    {
        perror("recv:");
    }
}

void ClearTcpClient(TcpC *c)
{
    close(c->sock);
    free(c);
}